跳到主要内容

组件通信与 v-model

父组件通过 props 传值,子组件通过 emits 请求更新。不要同时维护 prop 副本并用两个 watcher 相互同步,容易形成重复更新与状态来源混乱。

Vue 3:模型 prop 与更新事件​

<!-- Parent.vue -->
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const food = ref('苹果');
</script>

<template>
<Child v-model:food="food" />
<p>父组件:{{ food }}</p>
</template>
<!-- Child.vue -->
<script setup>
import { computed } from 'vue';
const props = defineProps({ food: String });
const emit = defineEmits(['update:food']);
const innerFood = computed({
get: () => props.food,
set: value => emit('update:food', value)
});
</script>

<template>
<input v-model="innerFood" />
</template>

v-model:food 等价于 :food="food" @update:food="food = $event"。默认无参数的组件 v-model 对应 modelValue 与 update:modelValue。

Vue 3.4+:defineModel 简写​

子组件的声明可替换为:

<script setup>
const food = defineModel('food', { type: String });
</script>

<template>
<input v-model="food" />
</template>

defineModel() 负责声明模型 prop 和事件,修改 ref 时请求父组件更新,不应当作任意共享可变状态。

Vue 2:sync 写法​

父组件使用 <Child :food.sync="food" />,子组件通过可写 computed 的 setter 执行 this.$emit('update:food', value)。Vue 3 中 .sync 已由带参数的 v-model 替代。

跨多层组件的上下文传递见 provide / inject。